package com.sanyue.reflect;

import org.junit.Test;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author sanyue
 * @version 1.0
 * @description: TODO
 * @date 2022/1/27 下午8:20
 */
public class TestReflect {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException {
        /**
         * 获取TargetObject类的Class对象并且创建TargetObject类实例
         */
        Class<?> tagetClass = Class.forName("com.sanyue.reflect.TargetObject");
        TargetObject targetObject = (TargetObject) tagetClass.newInstance();
        /**
         * 获取所有类中所有定义的方法
         */
        Method[] methods = tagetClass.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        /**
         * 获取指定方法并调用
         */
        Method publicMethod = tagetClass.getDeclaredMethod("publicMethod",
                String.class);

        publicMethod.invoke(targetObject, "sanyue");
        /**
         * 获取指定参数并对参数进行修改
         */
        Field field = tagetClass.getDeclaredField("value");
        //为了对类中的参数进行修改我们取消安全检查
        field.setAccessible(true);
        field.set(targetObject, "sanyue");
        /**
         * 调用 private 方法
         */
        Method privateMethod = tagetClass.getDeclaredMethod("privateMethod");
        //为了调用private方法我们取消安全检查
        privateMethod.setAccessible(true);
        privateMethod.invoke(targetObject);
    }

    @Test
    public void testReflect() throws Exception{
        /**
         * 获取TargetObject类的Class对象并且创建TargetObject类实例
         */
        // 1.类.class 实例化无需强转
        //Class<TargetObject> clazz = TargetObject.class;
        //2.对象Instance.getClass() 实例化无需强转
        //TargetObject target = new TargetObject();
        //Class<? extends TargetObject> clazz = target.getClass();
        //3.Class.forName("")  实例化需要强转
        //Class<?> clazz = Class.forName("com.sanyue.reflect.TargetObject");
        //4.ClassLoader.loadClass() 实例化需要强转
        Class<?> clazz = ClassLoader.getSystemClassLoader().loadClass("com.sanyue.reflect.TargetObject");
        TargetObject targetObject = (TargetObject) clazz.newInstance();
        /**
         * 获取所有类中所有定义的方法
         */
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        /**
         * 获取指定方法并调用
         */
        Method method = clazz.getDeclaredMethod("publicMethod",String.class);
        method.invoke(targetObject,"sanyue");
        /**
         * 获取指定参数并对参数进行修改--需要取消安全检查
         */
        Field value = clazz.getDeclaredField("value");
        value.setAccessible(true);
        value.set(targetObject,"sanyueya");
        /**
         * 调用 private 方法--需要取消安全检查
         */
        Method privateMethod = clazz.getDeclaredMethod("privateMethod");
        privateMethod.setAccessible(true);
        privateMethod.invoke(targetObject);

    }
}
